package com.suse.jd_system_server.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.suse.jd_system_server.dao.MapDao;
import com.suse.jd_system_server.entity.Hotel;
import com.suse.jd_system_server.entity.User;
import com.suse.jd_system_server.epmty.Locations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

/**
 * 百度地图api
 * 包含以下功能：
 * 功能：
 * 地点检索结果集格式
     * 格式：{status,message,results:[{xxx},{xxx}]}
     * results-demo:
     * {"name":"背包十年","location":{"lat":30.671116,"lng":104.077846},
     * "address":"四川省成都市青羊区三多里82号1栋","province":"四川省","city":"成都市",
     * "area":"青羊区","street_id":"dfdf5646b92779d10869d96f",
     * "telephone":"(028)81131619","detail":1,"uid":"dfdf5646b92779d10869d96f"}
 * 地点详情检索格式：
     *输入上个结果集中的uid，获得目标地点的详细信息
     *格式：
     *   {"status":0,"message":"ok",
     *   "result":{"uid":"be0cef1dad930274c6f02587","street_id":"be0cef1dad930274c6f02587",
     *   "name":"全季酒店(成都新会展中心店)","location":{"lng":104.07949417726,"lat":30.564384350711},
     *   "address":"成都市武侯区世纪城路166号西蜀廊桥11栋","province":"四川省","city":"成都市","area":"武侯区",
     *   "telephone":"(028)62038111",
     *   "detail_info":{"tag":"酒店;快捷酒店","navi_location":{"lng":104.08024300473,"lat":30.564550481277},
     *   "shop_hours":"","brand":"全季酒店","alias":[""],
     *   "detail_url":"http://api.map.baidu.com/place/detail?uid=be0cef1dad930274c6f02587&output=html&source=placeapi_v2",
     *   "type":"hotel","overall_rating":"4.6","service_rating":"4.5","facility_rating":"4.5",
     *   "hygiene_rating":"4.5","image_num":"169","comment_num":"40","favorite_num":"0","checkin_num":"0",
     *   "level":"舒适型","environment_exterior":"环球中心海洋乐园/世纪城新会展;双流国际机场;天府国际机场;成都南站;成都东站;锦城广场东;世纪城;城东客运中心;石羊客运站;锦城广场东地铁站-B口;世纪城地铁站-F口",
     *   "inner_facility":"衣架 雨伞 针线包 220V电压插座 多种规格电源插座 110V电压插座","hotel_service":"熨衣服务 24小时前台 快速入住退房 餐厅 商务服务 旅游交通图 洗衣用品 每日打扫 每日换毛巾 行李寄存 叫醒服务 每日换牙具 洗涤用具 熨斗/挂烫机 每日换被单 打扫工具 收费停车场"},
     *   "detail":1}}
 */
@Component
public class BaiduMapUtil {
    public static String URL = "https://api.map.baidu.com/place/v2/search?";//地址信息请求地址
    public static String DETAILURL = "https://api.map.baidu.com/place/v2/detail?";//地址详情请求地址
    public static String CODENIURL = "https://api.map.baidu.com/reverse_geocoding/v3?";//地址逆编码请求地址
    public static String CODEURL = "https://api.map.baidu.com/geocoding/v3?";//地址编码请求地址
    private static String AK = "0Eed0TeyLRDZvX513Q8GDcDQkq4AAuIs";//AK密钥
    private static MapDao dao;

    @Autowired
    public void setDao(MapDao dao) {
        BaiduMapUtil.dao = dao;
    }
    /**
     * 基础参数集
     * 根据检索关键词返回一个参数map集合，来自搜索模块
     * @return 参数集
     */
    static LinkedHashMap<String,String> getParams(){
        LinkedHashMap<String, String> params = new LinkedHashMap<>();
        params.put("output", "json");
        params.put("ak", AK);
        return params;
    }

    /**
     * 处理和解析地址并完成请求，此处暂时用作获取各个行政区的酒店信息列表
     * @param strUrl,百度api提供的访问地址
     * @param param，参数集
     * @return 结果集的json字符串
     * @throws Exception
     */
    static String requestGetAK(String strUrl , Map<String , String> param) throws Exception{
        if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) {
            return "";
        }

        StringBuffer queryString = new StringBuffer();
        queryString.append(strUrl);
        for (Map.Entry<?, ?> pair : param.entrySet()) {
            queryString.append(pair.getKey() + "=");
            //    第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            //    queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            //解决uid="abc",pair=uid中，""会被解析的问题
            String strValue = (String) pair.getValue();
            if (strValue.startsWith("\"") && strValue.endsWith("\"")) {
                strValue = strValue.substring(1, strValue.length() - 1);
            }
            queryString.append(UriUtils.encode(strValue, "UTF-8") + "&");
        }

        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }

        java.net.URL url = new URL(queryString.toString());
        System.out.println(queryString.toString());
        URLConnection httpConnection = (HttpURLConnection) url.openConnection();
        httpConnection.connect();

        InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
        BufferedReader reader = new BufferedReader(isr);
        StringBuffer buffer = new StringBuffer();
        String line;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        reader.close();
        isr.close();
        return buffer.toString();
    }

    /**
     * 获取大致地址信息并处理结果集
     * @param query，检索关键词
     * @param region，行政区
     * 可选参数：
     * output，输出格式
     * tag，检索次关键词，可以和query组合，非必须--可为""
     * @throws Exception
     */
    public static JsonNode getAddr(String query, String region) throws Exception {
        LinkedHashMap<String, String> params = getParams();
        params.put("query", query);
        params.put("region", region);
        String s = requestGetAK(URL, params);//百度API，数据查询
//        数据处理
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(s);
    }

    /**
     * 根据大致地址信息的uid获取地址详情结果集
     * @param uid，地址uid
     * @return
     */
    static JsonNode getDetail(String uid) throws Exception {
        LinkedHashMap<String, String> params = getParams();

        //查询单个详细地址
        params.put("scope", "2");
        params.put("uid",uid);
        String s = requestGetAK(DETAILURL, params);

        //处理数据
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(s);
    }


    /**
     * 地址解析：输入经纬度返回结构化地址
     * @param lng，经度
     * @param lat，维度
     * @return 结构化地址
     */
    public static String getAddress(Double lng,Double lat ) throws Exception {
        //逆编码地址
        LinkedHashMap<String, String> params = getParams();
        params.put("coordtype", "wgs84ll");
        params.put("extensions_poi", "0");
        params.put("location",lat+","+lng);
//        params.put("location","31.225696563611,121.49884033194");
        String s = requestGetAK(CODENIURL, params);

        //处理数据
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(s);
        return jsonNode.get("result").get("formatted_address").asText();
    }

    /**
     * 地址编码：传入结构化地址获取经纬度
     */
    public static Locations getAddressNi(String addr) throws Exception {
        Locations location = new Locations();
        LinkedHashMap<String, String> params = getParams();

        params.put("address", addr);

        String s = requestGetAK(CODEURL, params);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode node = objectMapper.readTree(s).get("result").get("location");

        location.setLng(node.get("lng").asDouble());
        location.setLat(node.get("lat").asDouble());
        return location;
    }


    /**
     * 获取用户城市名
     */
    public static String getUserCity(User user){
        String addr = user.getAddr();
        int starts = addr.indexOf("省");
        int ends = addr.indexOf("市");
        return addr.substring(starts+1,ends+1);
    }

    /**
     * 获取指定城市内的酒店经纬度对象数组
     */
    public static ArrayList<Locations>getLocations(String city){
        Locations location;
        ArrayList<Hotel> list = dao.getLocation(city);
        ArrayList<Locations> res = new ArrayList<>();
        for (Hotel h: list) {
            location = new Locations();
            location.setLng(h.getAddx());
            location.setLat(h.getAddy());
            res.add(location);
        }
        return res;
    }

    /**
     * 获取指定城市内的酒店名list
     */
    public static ArrayList<String> getHotels(String city){
        ArrayList<Hotel> hotels = dao.getLocation(city);
        ArrayList<String> list = new ArrayList<>();
        for (Hotel h: hotels) {
            list.add(h.getHotelName());
        }
        return list;
    }

    /**
     * 为调用者返回搜索集中特定的key集合
     * 需要递归获取key值，获取单个String依次存入list
     * 例如需要酒店名，调用时输入：getMapInfo("酒店","成都","name")
     * query-region，搜索关键词
     * key，jsonNode中的目标key
     * @return 目标key的list集合

    public static ArrayList<String> getMapInfo(String query,String region ,String key) throws Exception {
        ArrayList<String> list = new ArrayList<>();
        Iterator<JsonNode> elements = getJsonNode(query, region).get("results").elements();//获取结果集
        while(elements.hasNext()){
            JsonNode element = elements.next();
            list.add(String.valueOf(element.get(key)));
        }
        return list;
    }
    */


}
